package com.sikhyeon.datastructure.controller;

import com.sikhyeon.datastructure.model.Stack;
import javafx.animation.FadeTransition;
import javafx.animation.TranslateTransition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.io.IOException;

public class StackController {

    @FXML
    private VBox stackContainer;

    @FXML
    private StackPane messagePane;

    @FXML
    private Label messageLabel;

    private Stack stack = new Stack();
    private int valueCounter = 1;

    public void goBack(ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/sikhyeon/datastructure/view/MainView.fxml"));
        Parent root = loader.load();
        Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        Scene scene = new Scene(root, 800, 600); // 창 크기를 고정
        stage.setScene(scene);
        stage.show();
    }

    public void pushValue(ActionEvent event) {
        if (!stack.isFull() && stackContainer.getChildren().size() < Stack.MAX_SIZE) { // 스택이 가득 차있지 않을 때만 요소 추가
            int value = valueCounter++;
            stack.push(value);
            addStackElement(value);
        } else {
            showMessage("Stack overflow");
        }
    }

    public void popValue(ActionEvent event) {
        if (!stack.isEmpty() && !stackContainer.getChildren().isEmpty()) { // 스택이 비어있지 않을 때만 팝
            stack.pop();
            removeStackElement();
        } else if (!stackContainer.getChildren().isEmpty()) {
            removeStackElement();
        } else {
            showMessage("Stack underflow");
        }
    }
    public void initialize() {
        stack = new Stack();
        valueCounter = 1;
        stackContainer.getChildren().clear();
        showMessage("Stack initialized");
    }



    private void addStackElement(int value) {
        Rectangle rectangle = new Rectangle(100, 30, Color.LIGHTBLUE);
        rectangle.setArcWidth(10);
        rectangle.setArcHeight(10);
        Text text = new Text(String.valueOf(value));
        text.setFill(Color.BLACK);
        text.setTextAlignment(TextAlignment.CENTER);
        text.setX(rectangle.getX() + rectangle.getWidth() / 2 - text.getLayoutBounds().getWidth() / 2);
        text.setY(rectangle.getY() + rectangle.getHeight() / 2 + text.getLayoutBounds().getHeight() / 4);

        Group group = new Group();
        group.getChildren().addAll(rectangle, text);

        stackContainer.getChildren().add(0, group);

        // 애니메이션 추가
        TranslateTransition transition = new TranslateTransition(Duration.seconds(0.5), group);
        transition.setFromY(-stackContainer.getHeight() / 2);
        transition.setToY(0);
        transition.play();
    }

    private void removeStackElement() {
        if (!stackContainer.getChildren().isEmpty()) {
            Node node = stackContainer.getChildren().get(0);
            TranslateTransition transition = new TranslateTransition(Duration.seconds(0.5), node);
            transition.setToX(-stackContainer.getWidth()); // 좌측으로 이동
            transition.setOnFinished(e -> stackContainer.getChildren().remove(node));
            transition.play();
        }
    }

    private void showMessage(String message) {
        messageLabel.setText(message);
        FadeTransition fadeIn = new FadeTransition(Duration.seconds(0.5), messagePane);
        fadeIn.setFromValue(0);
        fadeIn.setToValue(1);
        fadeIn.play();

        FadeTransition fadeOut = new FadeTransition(Duration.seconds(0.5), messagePane);
        fadeOut.setFromValue(1);
        fadeOut.setToValue(0);
        fadeOut.setDelay(Duration.seconds(1.5));
        fadeOut.play();
    }
    public void resetStack(ActionEvent event) {
        initialize();
    }

}
